/*
 * ListChannelsPanel.java
 *
 * Created on 28 juin 2010, 21:54:29
 */
package darknet.application.chat.gui;

import darknet.application.chat.spec.Channel;
import darknet.application.chat.spec.ChatApplication;
import darknet.application.chat.spec.Session;
import darknet.core.spec.net.Node;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;

/**
 * A panel for listing available nodes and channels.
 * 
 * You can list nodes and channels.
 * You can start a private session.
 * You can create a new channel.
 * You can join a channel.
 *
 * @author Yoyo
 */
public class ListChannelsPanel extends JPanel {

    /** Serial version */
    private static final long serialVersionUID = 1L;

    /** Chat application */
    private ChatApplication application = null;

    /** Chat application panel */
    private ChatApplicationPanel master = null;

    /**
     * Initialise a ListChannels Panel.
     * 
     * @param application
     * @param master
     */
    ListChannelsPanel(ChatApplication application,
            ChatApplicationPanel master) {

        if (application == null) {
            throw new IllegalArgumentException("application is null");
        }
        this.application = application;

        if (master == null) {
            throw new IllegalArgumentException("master is invalid (null)");
        }
        this.master = master;

        initComponents();

        updateNodeList();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        btnJoin = new javax.swing.JButton();
        btnCreate = new javax.swing.JButton();
        btnRefreshChannels = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        listChannelsName = new javax.swing.JList();
        jPanel2 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        listNodesName = new javax.swing.JList();
        btnChat = new javax.swing.JButton();
        btnRefreshNodes = new javax.swing.JButton();

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Channels Available"));

        btnJoin.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        btnJoin.setText("Join");
        btnJoin.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnJoinActionPerformed(evt);
            }
        });

        btnCreate.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        btnCreate.setText("Create");
        btnCreate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCreateActionPerformed(evt);
            }
        });

        btnRefreshChannels.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        btnRefreshChannels.setText("Refresh");
        btnRefreshChannels.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRefreshChannelsActionPerformed(evt);
            }
        });

        jScrollPane1.setViewportView(listChannelsName);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addComponent(btnCreate)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnRefreshChannels)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnJoin, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 385, Short.MAX_VALUE)
                .addGap(18, 18, 18)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnRefreshChannels, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnCreate, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnJoin, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Nodes Available"));

        jScrollPane2.setViewportView(listNodesName);

        btnChat.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        btnChat.setText("Chat With");
        btnChat.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnChatActionPerformed(evt);
            }
        });

        btnRefreshNodes.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        btnRefreshNodes.setText("Refresh");
        btnRefreshNodes.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRefreshNodesActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addComponent(btnRefreshNodes, javax.swing.GroupLayout.PREFERRED_SIZE, 94, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnChat, javax.swing.GroupLayout.PREFERRED_SIZE, 105, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 374, Short.MAX_VALUE)
                .addGap(18, 18, 18)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(btnChat, javax.swing.GroupLayout.DEFAULT_SIZE, 47, Short.MAX_VALUE)
                    .addComponent(btnRefreshNodes, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGap(18, 18, 18)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents
  
    private void btnRefreshChannelsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshChannelsActionPerformed

        btnRefreshChannels.setEnabled(false);
        btnRefreshChannels.setText("Refreshing...");

        updateChannelList();
        
        btnRefreshChannels.setText("Refresh");
        btnRefreshChannels.setEnabled(true);
    }//GEN-LAST:event_btnRefreshChannelsActionPerformed

    private void btnCreateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCreateActionPerformed

        btnCreate.setEnabled(false);
        btnCreate.setText("Creating...");

        // TODO Make a more sexy dialog...
        // Prompt the user for type the channel name.
        final String channelName = JOptionPane.showInputDialog(
                "Type the channel name");

        // Try yo create the channel
        try {

            application.createChannel(channelName);

        } catch (IllegalArgumentException ex) {

            JOptionPane.showMessageDialog(
                    null, ex.getLocalizedMessage(), "Exception",
                    JOptionPane.WARNING_MESSAGE);
        }

        updateChannelList();

        btnCreate.setText("Create");
        btnCreate.setEnabled(true);
    }//GEN-LAST:event_btnCreateActionPerformed

    private void btnJoinActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnJoinActionPerformed

        btnJoin.setEnabled(false);
        btnJoin.setText("Joining...");

        new SwingWorker<Object, Object>() {

            @Override
            protected Object doInBackground() {

                // Get the selected channel name
                String chanName = (String) listChannelsName.getSelectedValue();
                try {

                    Channel channel = application.getChannel(chanName);

                    // Channel not found ?
                    if (channel == null) {

                        JOptionPane.showMessageDialog(
                                null, "Channel not found", "Not found",
                                JOptionPane.WARNING_MESSAGE);
                        
                        updateChannelList();

                    }

                    // Join the channel and show the channel frame
                    else {
                        master.newChannelStart(channel);
                    }

                } catch (IOException ex) {

                    JOptionPane.showMessageDialog(
                            null, ex.getLocalizedMessage(), "Exception",
                            JOptionPane.WARNING_MESSAGE);
                }

                btnJoin.setText("Join");
                btnJoin.setEnabled(true);

                return null;
            }
        }.execute();
    }//GEN-LAST:event_btnJoinActionPerformed

    private void btnRefreshNodesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshNodesActionPerformed
        
        btnRefreshNodes.setEnabled(false);
        btnRefreshNodes.setText("Refreshing...");

        new SwingWorker<Object, Object>() {

            @Override
            protected Object doInBackground() throws Exception {

                updateNodeList();

                btnRefreshNodes.setText("Refresh");
                btnRefreshNodes.setEnabled(true);
                return null;
            }

        }.execute();
    }//GEN-LAST:event_btnRefreshNodesActionPerformed

    private void btnChatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnChatActionPerformed

        btnChat.setEnabled(false);
        btnChat.setText("Preparing...");
        
        new SwingWorker<Object, Object>() {

            @Override
            protected Object doInBackground() {
                
                String nodeName = (String) listNodesName.getSelectedValue();
                if (nodeName == null) {
                    return null;
                }
                
                // Create the channel.
                Session session = null;
                try {
                    session = application.createSession(nodeName);
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(btnChat,
                            "IOException while creating the session : "
                            + ex.getLocalizedMessage(),
                            "IOException", JOptionPane.OK_OPTION);
                    return null;
                }

                // Notify the master panel of session start
                master.newSessionStart(session);
                
                btnChat.setText("Chat With");
                btnChat.setEnabled(true);
                
                return null;
            }
            
        }.execute();
    }//GEN-LAST:event_btnChatActionPerformed

    /**
     * Update the node list
     */
    private void updateNodeList() {

        List<String> nodes = new ArrayList<String>(10);
        for (Node node : application.getReachableNodes()) {
            nodes.add(node.getName());
        }
        
        listNodesName.setListData(nodes.toArray());
    }

    /**
     * Update the channel list
     */
    void updateChannelList() {

        List<String> channels = new ArrayList<String>(10);

        // Get the list of network channels and add them to the string list
        try {
            
            for (Channel channel : application.getChannels()) {
                channels.add(channel.getName());
            }

        } catch (IOException ex) {
            
            JOptionPane.showMessageDialog(
                    null, ex.getLocalizedMessage(), "Exception", 
                    JOptionPane.WARNING_MESSAGE);
        }

        // Update the UI
        listChannelsName.setListData(channels.toArray());
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnChat;
    private javax.swing.JButton btnCreate;
    private javax.swing.JButton btnJoin;
    private javax.swing.JButton btnRefreshChannels;
    private javax.swing.JButton btnRefreshNodes;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JList listChannelsName;
    private javax.swing.JList listNodesName;
    // End of variables declaration//GEN-END:variables

}
